package com.creative.xcx.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.creative.config.AppConfig;
import com.creative.core.controller.BaseController;
import com.creative.core.domain.AjaxResult;
import com.creative.core.page.TableDataInfo;
import com.creative.utils.MaterialCheckUtils;
import com.creative.xcx.domain.Material;
import com.creative.xcx.domain.dto.MpUserDto;
import com.creative.xcx.service.MaterialService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.creative.constant.Constants.*;

/**
 * @author ling
 * @description 素材信息
 * @date 2025-03-02
 */
@RestController
@RequestMapping(value = "/Material")
public class MaterialController extends BaseController {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private AppConfig appConfig;

    @Resource
    private MaterialService materialService;

    @Resource
    private MaterialCheckUtils materialCheckUtils;



    /**
     * 新增
     *
     * @author ling
     * @date 2025/03/02
     **/
    @PostMapping
    public AjaxResult insert(@RequestBody Material material) {
        return toAjax(materialService.insert(material));
    }

    /**
     * 刪除单个
     *
     * @author ling
     * @date 2025/03/02
     **/
    @DeleteMapping("/{materialId}")
    public AjaxResult delete(@PathVariable("materialId") String materialId) {
        return toAjax(materialService.delete(materialId));
    }

    /**
     * 批量刪除
     *
     * @author ling
     * @date 2025/03/02
     **/

    @DeleteMapping("/batch")
    public AjaxResult deleteBatch(@RequestBody String[] ids) {
        return toAjax(materialService.deleteBatch(ids));
    }


    /**
     * 更新
     *
     * @author ling
     * @date 2025/03/02
     **/
    @PutMapping("/update")
    public AjaxResult update(@RequestBody Material material) {
        return toAjax(materialService.update(material));
    }


    /**
     * 查询 根据主键 id 查询
     *
     * @author ling
     * @date 2025/03/02
     **/
    @GetMapping(value = "/{materialId}")
    public AjaxResult selectById(@PathVariable("materialId") String materialId) {

        if (materialId == null) {
            return error("参数为空");
        }
        return success(materialService.selectById(materialId.trim()));
    }

    /**
     * 小程序获取素材信息
     *
     * @author ling
     * @date 2025/03/02
     **/
    @GetMapping(value = "/app/{materialId}")
    public AjaxResult selectAppById(@PathVariable("materialId") String materialId) {
        if (materialId == null) {
            return error("参数为空");
        }
        return success(materialService.selectAppById(materialId.trim()));
    }

    /**
     * 查询 分页查询(带条件)
     *
     * @author ling
     * @date 2025/03/02
     **/
    @GetMapping("/list")
    public TableDataInfo selectMaterialList(Material material) {
        logger.info("查询所有数据 分页查询(带条件)：{}", material);
        return materialService.selectMaterialList(material);
    }

    /**
     * 获取小程序素材列表
     *
     * @param material 素材
     * @return {@link TableDataInfo }
     * @author ling
     * @date 2025/03/09
     */
    @GetMapping("/mp/list")
    public TableDataInfo getMpMaterialList(Material material) {
        logger.info("获取小程序素材列表:{}", material);
        return materialService.selectMaterialList(material);
    }

    /**
     * 获取每日推荐素材
     *
     * @param index 素材
     * @return {@link TableDataInfo }
     * @author ling
     * @date 2025/03/16
     */
    @GetMapping("/mp/randomList/")
    public AjaxResult getMpMaterialRandomList(Long index) {

        logger.info("获取随机推荐:{}", index);
        if (index == null) {
            return error("参数为空");
        }
//        对index进行分辨
        if (index == 0) {
//            使用图片数组
            return success(materialService.getRandomMaterialList(IMAGE_SUFFIX, CACHE_RANDOM_MATERIAL_IMAGE_KEY));
        }
        if (index == 1) {
//            音频素材
            return success(materialService.getRandomMaterialList(AUDIO_SUFFIX, CACHE_RANDOM_MATERIAL_AUDIO_KEY));

        }
        if (index == 2) {
//            视频素材
            return success(materialService.getRandomMaterialList(VIDEO_SUFFIX, CACHE_RANDOM_MATERIAL_VIDEO_KEY));
        }
        return null;
    }


    /**
     * 素材上传页的素材推荐
     *
     * @return {@link AjaxResult }
     * @author ling
     * @date 2025/04/12
     */
    @GetMapping("/mp/recommend")
    public AjaxResult getMpMaterialRecommend() {
//   素材上传页的素材推荐
        return success(materialService.getMpMaterialRecommend());
    }

    /**
     * 批量导出
     *
     * @author ling
     * @date 2025/03/02
     **/
    @PostMapping("/export")
    public void export(@RequestBody String[] ids, HttpServletResponse response) throws IOException {
        //        判断ids是否为空
        if (ids == null || ids.length == 0) {
            // ids 为空或未初始化时执行的代码
            throw new RuntimeException("ids为空");
        }
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("素材信息" + System.currentTimeMillis(), StandardCharsets.UTF_8);
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), Material.class)
                .sheet("素材信息")
                .doWrite(() -> {
                    // 查询数据
                    return materialService.exportBatch(ids);
                });
        logger.info("导出成功");
    }

    /**
     * 素材的关键词（标签查找）
     *
     * @param keyword 关键词
     * @return {@link AjaxResult }
     * @author ling
     * @date 2025/04/09
     */
    @GetMapping("/keyword")
    public AjaxResult getMaterialByKeyword(String keyword) {
        logger.info("关键词查找：{}", keyword);
        if (keyword == null) {
            return success(null);
        }
        return success(materialService.getMaterialKeyword(keyword));
    }

    /**
     * 按关键字搜索素材
     *
     * @param material 素材
     * @return {@link TableDataInfo }
     * @author ling
     * @date 2025/04/09
     */
    @PostMapping("/search")
    public TableDataInfo searchMaterialByKeyword(@RequestBody Material material) {
        logger.info("关键词搜索：{}", material.getMaterialTags());
        if (material.getMaterialTags() == null) {
//            无查询关键字
            return TableDataInfo.success();
        }
        return materialService.searchMaterialByKeyword(material);
    }

    /**
     * 素材安全内容检测
     *
     * @param material 素材
     * @return {@link AjaxResult }
     * @author ling
     * @date 2025/05/12
     */
    @PostMapping("/check")
    public AjaxResult checkMaterial(@RequestBody Material material) {

        try {
            //        检测素材标题
            if (StrUtil.isBlank(material.getMaterialTitle())) {
                return error("素材标题不能为空");
            }
//        返回true是通过检测
            if (!checkMaterialContent(material.getMaterialTitle())) {
                return error("素材标题内容有敏感词");
            }

//        如果素材缩略图不为空，则检测素材缩略图
            if (StrUtil.isNotBlank(material.getThumbnailUrl())) {
                if (!materialCheckUtils.checkMaterialImage(material.getThumbnailUrl())) {
                    return error("素材缩略图含有违规内容");
                }
            }
            // 检测素材摘要
            String materialSummary = material.getMaterialSummary();
            if (StrUtil.isNotBlank(materialSummary)) {
                if (!checkMaterialContent(materialSummary)) {
                    return error("素材摘要内容有敏感词");
                }
            }

            if (StrUtil.isBlank(material.getMaterialUrl())) {
                return error("素材不能为空");
            }

        } catch (Exception e) {
            // 记录日志并返回通用错误信息，防止因敏感词校验导致流程中断
            logger.error("安全校验过程中发生异常", e);
            throw new RuntimeException("安全校验失败",e);
        }
        return toAjax(materialService.insert(material));
    }

    /**
     * 检查素材文本安全
     *
     * @param content 内容
     * @return {@link Boolean }
     * @author ling
     * @date 2025/05/12
     */
    public boolean checkMaterialContent(String content) {

        //       1.获取接口调用凭据
        //        查看redis缓存中是否存在小程序的access_token
        String accessToken;
        if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(CACHE_ACCESS_TOKEN_KEY))) {
            //            存在，则使用缓存的access_token
            accessToken = stringRedisTemplate.opsForValue().get(CACHE_ACCESS_TOKEN_KEY);
        } else {
            // 获取 access_token 并缓存
            StrBuilder tokenUrl = StrBuilder.create()
                    .append("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential")
                    .append("&appid=").append(appConfig.getXcxAppId())
                    .append("&secret=").append(appConfig.getXcxAppSecret());
            String tokenResult = HttpUtil.get(tokenUrl.toString());
            // 解析 JSON 获取 accessToken，并缓存到 Redis
            accessToken = materialCheckUtils.parseAccessTokenFromJson(tokenResult);
            if (accessToken == null) {
                return false;
            }
//            设置缓存
            stringRedisTemplate.opsForValue().set(CACHE_ACCESS_TOKEN_KEY, accessToken, 7200, TimeUnit.SECONDS);
        }
//        获取用户openId
        SaSession session = StpUtil.getSession();
        String userId = (String) StpUtil.getLoginId();
        MpUserDto mpSession = (MpUserDto) session.get("MpSession" + userId);
        logger.info("用户openId为：" + mpSession.getOpenId());

        // 发起内容安全检测请求
        StrBuilder url = StrBuilder.create()
                .append("https://api.weixin.qq.com/wxa/msg_sec_check?access_token=")
                .append(accessToken);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("openid", mpSession.getOpenId());
        paramMap.put("scene", 1);
        paramMap.put("version", 2);
        paramMap.put("content", content);

        String response = HttpUtil.post(String.valueOf(url), JSONUtil.toJsonStr(paramMap));
        // 解析响应，判断是否合法
        return materialCheckUtils.isContentSafe(response);
    }

}
